package test.tftp;

import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;


public class GuiTFTP extends JFrame
{
    private static final long serialVersionUID = 4146651734284697967L;

    boolean work = false; // 启动、关闭控制变量

    private String log; // 日志文件路径

    private String share; // 根目录文件夹路径

    private TftpServer serv; // 服务类

    private Para param = new Para(false); // 控制显示传输过程

    public GuiTFTP()
    {
        try
        {
            jbInit();
        }
        catch (Exception ex)
        {
            ex.printStackTrace();
        }
    }

    private void jbInit() throws Exception
    {
        Toolkit kit = Toolkit.getDefaultToolkit();
        Dimension screenSize = kit.getScreenSize();
        setBounds(screenSize.width / 4, screenSize.height / 4, screenSize.width / 2, screenSize.height / 2);
        setTitle("TFTP Server(已关闭)");
        log = new File(".").getAbsolutePath();
        share = new File(".").getAbsolutePath();
        try
        {
            File f = new File(log + "");
            if (!f.exists())
            {
                FileWriter logfile = new FileWriter(log + "");
                Date date = new Date();
                DateFormat d = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                String str = d.format(date);
                logfile.write("日志创建时间：" + str);
                logfile.close();

                jTextArea1.setText("日志目录更改为：" + log);
            }
        }
        catch (IOException ex)
        {
        }
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setJMenuBar(jMenuBar1);
        jMenu1.setText("设置");
        jMenu2.setText("帮助");
        jMenuItem1.setText("设置日志目录");
        jMenuItem1.addActionListener(new Gui_jMenuItem1_actionAdapter(this));
        jMenuItem2.setText("设置根目录");
        jMenuItem2.addActionListener(new Gui_jMenuItem2_actionAdapter(this));
        jMenuItem3.setText("作者");
        jMenuItem3.addActionListener(new Gui_jMenuItem3_actionAdapter(this));
        jMenu3.setText("文件");
        jMenuItem4.setText("日志");
        jMenuItem4.addActionListener(new Gui_jMenuItem4_actionAdapter(this));
        jTextArea1.setEditable(false);
        jTextArea1.setText("欢迎使用   显示传输过程功能已关闭");
        jMenuItem5.setText("显示日志目录");
        jMenuItem5.addActionListener(new Gui_jMenuItem5_actionAdapter(this));
        jMenuItem6.setText("显示根目录");
        jMenuItem6.addActionListener(new Gui_jMenuItem6_actionAdapter(this));
        jMenu4.setText("启动/关闭");
        jMenuItem7.setText("启动TFTP");
        jMenuItem7.addActionListener(new Gui_jMenuItem7_actionAdapter(this));
        jMenuItem8.setText("关闭TFTP");
        jMenuItem8.addActionListener(new Gui_jMenuItem8_actionAdapter(this));
        jMenuItem9.setText("显示传输过程");
        jMenuItem9.addActionListener(new Gui_jMenuItem9_actionAdapter(this));
        jMenuItem10.setText("不显示传输过程");
        jMenuItem10.addActionListener(new Gui_jMenuItem10_actionAdapter(this));
        jMenuBar1.add(jMenu3);
        jMenuBar1.add(jMenu1);
        jMenuBar1.add(jMenu4);
        jMenuBar1.add(jMenu2);
        jMenu1.add(jMenuItem1);
        jMenu1.add(jMenuItem2);
        jMenu1.add(jMenuItem5);
        jMenu1.add(jMenuItem6);
        jMenu1.add(jMenuItem9);
        jMenu1.add(jMenuItem10);
        jMenu2.add(jMenuItem3);
        jMenu3.add(jMenuItem4);
        this.getContentPane().add(new JScrollPane(jTextArea1), java.awt.BorderLayout.CENTER);
        jMenu4.add(jMenuItem7);
        jMenu4.add(jMenuItem8);
    }

    public static void main(String[] args)
    {
        new GuiTFTP().setVisible(true);
    }

    JMenuBar jMenuBar1 = new JMenuBar();

    JMenu jMenu1 = new JMenu();

    JMenu jMenu2 = new JMenu();

    JMenuItem jMenuItem1 = new JMenuItem();

    JMenuItem jMenuItem2 = new JMenuItem();

    JMenuItem jMenuItem3 = new JMenuItem();

    JMenu jMenu3 = new JMenu();

    JMenuItem jMenuItem4 = new JMenuItem();

    JTextArea jTextArea1 = new JTextArea();

    JMenuItem jMenuItem5 = new JMenuItem();

    JMenuItem jMenuItem6 = new JMenuItem();

    JMenu jMenu4 = new JMenu();

    JMenuItem jMenuItem7 = new JMenuItem();

    JMenuItem jMenuItem8 = new JMenuItem();

    JMenuItem jMenuItem9 = new JMenuItem();

    JMenuItem jMenuItem10 = new JMenuItem();

    public void jMenuItem1_actionPerformed(ActionEvent e)
    {
        JFileChooser fc = new JFileChooser();
        fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
        int RetVal = fc.showOpenDialog(this);
        if (RetVal == JFileChooser.APPROVE_OPTION)
        {
            try
            {
                System.out.println(log);
                log = fc.getSelectedFile().getPath();
                FileWriter logfile = new FileWriter(log + "");
                Date date = new Date();
                DateFormat d = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                String str = d.format(date);
                logfile.write("日志创建时间：" + str);
                logfile.close();
                jTextArea1.setText("日志目录更改为：" + log);
            }
            catch (IOException ex)
            {
            }
        }
    }

    public void jMenuItem2_actionPerformed(ActionEvent e)
    {
        JFileChooser fc = new JFileChooser();
        fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
        int RetVal = fc.showOpenDialog(this);
        if (RetVal == JFileChooser.APPROVE_OPTION)
        {
            share = fc.getSelectedFile().getPath();
            jTextArea1.setText("根目录更改为：" + share);
        }
    }

    public void jMenuItem4_actionPerformed(ActionEvent e)
    {
        try
        {
            File file = new File(log + ""); // 获得文件路径
            FileReader in = new FileReader(file); // 创建字符流对文件进行读取
            int size = (int) file.length(); // 检测文件大小
            char[] data = new char[size]; // 以分配空间
            in.read(data, 0, size - 0); // 读取字符
            jTextArea1.setText(new String(data)); // 在文本区域中显示字符
            in.close();
        }
        catch (FileNotFoundException ex)
        {
        }
        catch (IOException ex)
        {
        }
    }

    public void jMenuItem3_actionPerformed(ActionEvent e)
    {
        jTextArea1.setText("BUPT Zheng Cheng");
    }

    public void jMenuItem5_actionPerformed(ActionEvent e)
    {
        jTextArea1.setText("日志目录为：" + log);
    }

    public void jMenuItem6_actionPerformed(ActionEvent e)
    {
        jTextArea1.setText("根目录为：" + share);
    }

    public void jMenuItem7_actionPerformed(ActionEvent e)
    {
        work = true;
        serv = new TftpServer();
        serv.start();
        jTextArea1.setText("TFTP 已经启动");
        setTitle("TFTP server(已经启动)");
    }

    public void jMenuItem8_actionPerformed(ActionEvent e)
    {
        work = false;
        serv = null;
        jTextArea1.setText("TFTP 已经关闭");
        setTitle("TFTP server(已经关闭)");
    }

    class TftpServer extends Thread
    {
        // tftp数据包类型定义 (opcode)
        final static int RRQ = 1;

        final static int WRQ = 2;

        final static int DAT = 3;

        final static int ACK = 4;

        final static int ERR = 5;

        public void run()
        {
            try
            {
                DatagramSocket dskt = new DatagramSocket(69); // 监听69号端口
                byte[] buf = new byte[516]; // 定义冲区
                DatagramPacket dpkt = new DatagramPacket(buf, 516); // UDP pcket
                byte[] fname; // 文件名
                byte[] fmode; // 文件模式
                while (work)
                {
                    dskt.receive(dpkt);
//                    String hostIP = dpkt.getAddress().getHostAddress();
                    // if (!hostIP.startsWith("118.229.")){ //不是这个网段的直接忽略
                    // continue;
                    // }
                    byte[] data = dpkt.getData(); // 收到的数据
                    int opcode = (data[0] << 8) + data[1]; // 获取操作码
                    if (opcode != RRQ && opcode != WRQ)
                    { // 只处理RRQ、WRQ
                        byte[] error = new byte[5]; // 至少5个字节
                        error[0] = (byte) ((ERR >> 8) & 0xFF);
                        error[1] = (byte) (ERR & 0xFF);
                        error[2] = (byte) 0;
                        error[3] = (byte) 0;
                        error[4] = (byte) 0;
                        dpkt.setData(error); // dpk已经包含了客户端的 ip 和 端口号
                        dskt.send(dpkt);
                    }
                    else
                    {
                        int len; // len : Filename长度
                        int len1; // len1 : Mode长度
                        for (len = 0; data[len + 2] != 0; len++); // 计算Filename长度
                        fname = new String(data, 2, len).getBytes();
                        for (len1 = 0; data[2 + len + 1 + len1] != 0; len1++); // 计算Mode长度
                        fmode = new String(data, 2 + len + 1, len1).getBytes();
                        if (new String(fmode).equals("octet"))
                            new ClientThread(dpkt.getAddress(), dpkt.getPort(), opcode, fname, fmode, log, share,
                                    jTextArea1, param);
                        else
                        { // 只能用 octet 模式传输文件 回传一个错误信息
                            String msg = "please use the octet mode!";
                            byte[] bytes = new byte[516];
                            bytes[0] = (byte) ((ERR >> 8) & 0xFF);
                            bytes[1] = (byte) (ERR & 0xFF);
                            bytes[2] = (byte) 0;
                            bytes[3] = (byte) 0;
                            System.arraycopy(msg.getBytes(), 0, bytes, 4, (msg.getBytes()).length);
                            bytes[4 + msg.length()] = 0;
                            dpkt.setData(bytes);
                            try
                            {
                                dskt.send(dpkt);
                            }
                            catch (IOException ex)
                            {
                            }
                        }
                    }
                }
                dskt.close();
            }
            catch (SocketException ex)
            {
            }
            catch (IOException ex)
            {
            }
        }
    }

    public void jMenuItem9_actionPerformed(ActionEvent e)
    {
        param.setDetail(true);
        jTextArea1.setText("启动 \"显示传输过程\" 功能");
    }

    public void jMenuItem10_actionPerformed(ActionEvent e)
    {
        param.setDetail(false);
        jTextArea1.setText("关闭 \"显示传输过程\" 功能");
    }
}

class Gui_jMenuItem9_actionAdapter implements ActionListener
{
    private GuiTFTP adaptee;

    Gui_jMenuItem9_actionAdapter(GuiTFTP adaptee)
    {
        this.adaptee = adaptee;
    }

    public void actionPerformed(ActionEvent e)
    {
        adaptee.jMenuItem9_actionPerformed(e);
    }
}

class Gui_jMenuItem10_actionAdapter implements ActionListener
{
    private GuiTFTP adaptee;

    Gui_jMenuItem10_actionAdapter(GuiTFTP adaptee)
    {
        this.adaptee = adaptee;
    }

    public void actionPerformed(ActionEvent e)
    {
        adaptee.jMenuItem10_actionPerformed(e);
    }
}

class Gui_jMenuItem8_actionAdapter implements ActionListener
{
    private GuiTFTP adaptee;

    Gui_jMenuItem8_actionAdapter(GuiTFTP adaptee)
    {
        this.adaptee = adaptee;
    }

    public void actionPerformed(ActionEvent e)
    {
        adaptee.jMenuItem8_actionPerformed(e);
    }
}

class Gui_jMenuItem7_actionAdapter implements ActionListener
{
    private GuiTFTP adaptee;

    Gui_jMenuItem7_actionAdapter(GuiTFTP adaptee)
    {
        this.adaptee = adaptee;
    }

    public void actionPerformed(ActionEvent e)
    {
        adaptee.jMenuItem7_actionPerformed(e);
    }
}

class Gui_jMenuItem5_actionAdapter implements ActionListener
{
    private GuiTFTP adaptee;

    Gui_jMenuItem5_actionAdapter(GuiTFTP adaptee)
    {
        this.adaptee = adaptee;
    }

    public void actionPerformed(ActionEvent e)
    {
        adaptee.jMenuItem5_actionPerformed(e);
    }
}

class Gui_jMenuItem6_actionAdapter implements ActionListener
{
    private GuiTFTP adaptee;

    Gui_jMenuItem6_actionAdapter(GuiTFTP adaptee)
    {
        this.adaptee = adaptee;
    }

    public void actionPerformed(ActionEvent e)
    {
        adaptee.jMenuItem6_actionPerformed(e);
    }
}

class Gui_jMenuItem4_actionAdapter implements ActionListener
{
    private GuiTFTP adaptee;

    Gui_jMenuItem4_actionAdapter(GuiTFTP adaptee)
    {
        this.adaptee = adaptee;
    }

    public void actionPerformed(ActionEvent e)
    {
        adaptee.jMenuItem4_actionPerformed(e);
    }
}

class Gui_jMenuItem3_actionAdapter implements ActionListener
{
    private GuiTFTP adaptee;

    Gui_jMenuItem3_actionAdapter(GuiTFTP adaptee)
    {
        this.adaptee = adaptee;
    }

    public void actionPerformed(ActionEvent e)
    {
        adaptee.jMenuItem3_actionPerformed(e);
    }
}

class Gui_jMenuItem1_actionAdapter implements ActionListener
{
    private GuiTFTP adaptee;

    Gui_jMenuItem1_actionAdapter(GuiTFTP adaptee)
    {
        this.adaptee = adaptee;
    }

    public void actionPerformed(ActionEvent e)
    {
        adaptee.jMenuItem1_actionPerformed(e);
    }
}

class Gui_jMenuItem2_actionAdapter implements ActionListener
{
    private GuiTFTP adaptee;

    Gui_jMenuItem2_actionAdapter(GuiTFTP adaptee)
    {
        this.adaptee = adaptee;
    }

    public void actionPerformed(ActionEvent e)
    {
        adaptee.jMenuItem2_actionPerformed(e);
    }
}
